home *** CD-ROM | disk | FTP | other *** search
- Subject: v17i072: Zoo archive program, Part09/10
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Rahul Dhesi <bsu-cs!dhesi@iuvax.cs.indiana.edu>
- Posting-number: Volume 17, Issue 72
- Archive-name: zoo2/part09
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 9 (of 10)."
- # Wrapped by rsalz@papaya.bbn.com on Thu Feb 2 18:04:05 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'zooio.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'zooio.h'\"
- else
- echo shar: Extracting \"'zooio.h'\" \(2074 characters\)
- sed "s/^X//" >'zooio.h' <<'END_OF_FILE'
- X/* @(#) zooio.h 2.7 88/01/27 19:39:24 */
- X
- X/*
- XDeclarations for portable I/O
- X
- XThe contents of this file are hereby placed in the public domain.
- X
- X -- Rahul Dhesi 1988/01/24
- X*/
- X#ifndef OK_STDIO
- X#include <stdio.h>
- X#define OK_STDIO
- X#endif
- X
- X#ifndef PARMS
- X#ifdef LINT_ARGS
- X#define PARMS(x) x
- X#else
- X#define PARMS(x) ()
- X#endif
- X#endif
- X
- X/*
- XIn theory, all I/O using buffered files could be replaced with unbuffered
- XI/O simply by changing the following definitions. This has not been tried
- Xout yet, and there may be some remaining holes in the scheme. On systems
- Xwith limited memory, it might prove necessary to use unbuffered I/O
- Xonly.
- X*/
- Xtypedef FILE *ZOOFILE;
- X#define NOFILE ((ZOOFILE) 0)
- X#define NULLFILE ((ZOOFILE) -1) /* or any unique value */
- X#define STDOUT stdout
- X
- X#ifdef FILTER
- X#define STDIN stdin
- X#endif
- X
- X#ifdef IO_MACROS
- X#define zooread(file, buffer, count) fread (buffer, 1, count, file)
- X#define zoowrite(file, buffer, count) \
- X (file == NULLFILE ? count : fwrite (buffer, 1, count, file))
- X#define zooseek(file, offset, whence) fseek (file, offset, whence)
- X#define zootell(file) ftell (file)
- X#else
- Xint zooread PARMS((ZOOFILE, char *, int));
- Xint zoowrite PARMS((ZOOFILE, char *, int));
- Xlong zooseek PARMS((ZOOFILE, long, int));
- Xlong zootell PARMS((ZOOFILE));
- X#endif /* IO_MACROS */
- X
- XZOOFILE zooopen PARMS((char *, char *));
- XZOOFILE zoocreate PARMS((char *));
- Xint zooclose PARMS((ZOOFILE));
- Xint zootrunc PARMS((ZOOFILE));
- X
- X#ifdef LINT_ARGS
- Xchar *choosefname (struct direntry *);
- Xchar *fullpath (struct direntry *);
- Xint frd_zooh (struct zoo_header *, ZOOFILE);
- Xint frd_dir (struct direntry *, ZOOFILE);
- Xint fwr_dir (struct direntry *, ZOOFILE);
- Xint fwr_zooh (struct zoo_header *, ZOOFILE);
- Xint readdir (struct direntry *, ZOOFILE, int);
- Xvoid rwheader (struct zoo_header *, ZOOFILE, int);
- Xvoid newdir (struct direntry *);
- Xvoid writedir (struct direntry *, ZOOFILE);
- X#else
- Xchar *choosefname ();
- Xchar *fullpath ();
- Xint frd_zooh ();
- Xint frd_dir ();
- Xint fwr_dir ();
- Xint fwr_zooh ();
- Xint readdir ();
- Xvoid rwheader ();
- Xvoid newdir ();
- Xvoid writedir ();
- X#endif
- END_OF_FILE
- if test 2074 -ne `wc -c <'zooio.h'`; then
- echo shar: \"'zooio.h'\" unpacked with wrong size!
- fi
- # end of 'zooio.h'
- fi
- if test -f 'zoomem.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'zoomem.h'\"
- else
- echo shar: Extracting \"'zoomem.h'\" \(2456 characters\)
- sed "s/^X//" >'zoomem.h' <<'END_OF_FILE'
- X/* @(#) zoomem.h 2.1 87/12/25 12:26:18 */
- X
- X/*
- XThe contents of this file are hereby released to the public domain.
- X
- X -- Rahul Dhesi 1986/11/14
- X
- XDefines parameters used for memory allocation.
- X
- X Xenix notes: Under Xenix release 3.0 on an Intel 310 machine with an
- X 80286 cpu, memory is very tight when the small memory model is used.
- X Ooz won't fit if the buffers are 2 K for input and 6 K for output.
- X It does fit if both input and output buffers are 1 K each. Under
- X the large memory model there is no problem. Zoo requires the large
- X memory model.
- X
- X AT&T 3B2: There seem to be no problem at all. Buffers can always
- X be 8192 each.
- X*/
- X
- X#ifdef OOZ
- X#define IN_BUF_SIZE 8192
- X#define OUT_BUF_SIZE 8192
- X#else
- X#define IN_BUF_SIZE 8192
- X#define OUT_BUF_SIZE 8192
- X#endif
- X
- X#define MEM_BLOCK_SIZE (IN_BUF_SIZE + OUT_BUF_SIZE)
- X
- X/*
- XLIST_SIZE is the size of the list built by Zoo to hold all filenames
- Xencountered in an archive. This is used to know when to replace an
- Xalready existing file. The date and time stored with the filename is
- Xused in comparisons when an archive update has been requested. To
- Xadd a file to an archive, the archive must not already have more than
- XLIST_SIZE files in it.
- X
- XZOOCOUNT is the number of archive names that may be matched by the
- Xarchive filespec specified for a list.
- X
- XMAXADD is the number of filenames that may be added to an archive
- Xat one go. The total number of files that an archive may contain
- Xis not determined by MAXADD but is determined by LIST_SIZE.
- X
- XIf USE_MALLOC is defined it tells the memory allocation routine
- Xemalloc() not to bother with maintaining its own memory blocks but just to
- Xpass on requests to the library function malloc(). If USE_MALLOC is not
- Xdefined, emalloc() does its own memory management to save overhead on a
- Xmachine with limited memory.
- X*/
- X
- X#ifdef SMALL_MEM
- X#define LIST_SIZE (200)
- X#define ZOOCOUNT (30)
- X#define MAXADD (100)
- X#define USE_MALLOC
- X#endif
- X
- X#ifdef MED_MEM
- X#define LIST_SIZE (400)
- X#define ZOOCOUNT (50)
- X#define MAXADD (200)
- X#define USE_MALLOC
- X#endif
- X
- X#ifdef BIG_MEM
- X#define LIST_SIZE (4000)
- X#define ZOOCOUNT (400)
- X#define MAXADD (4000)
- X#define USE_MALLOC
- X#endif
- X
- X/* Customizable sizes */
- X#ifdef SPEC_MEM
- X#define LIST_SIZE (600)
- X#define ZOOCOUNT (100)
- X#define MAXADD (400)
- X#endif
- X
- Xextern char *out_buf_adr; /* global I/O buffer */
- END_OF_FILE
- if test 2456 -ne `wc -c <'zoomem.h'`; then
- echo shar: \"'zoomem.h'\" unpacked with wrong size!
- fi
- # end of 'zoomem.h'
- fi
- if test -f 'zooadd.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'zooadd.c'\"
- else
- echo shar: Extracting \"'zooadd.c'\" \(25720 characters\)
- sed "s/^X//" >'zooadd.c' <<'END_OF_FILE'
- X#ifndef LINT
- X/* @(#) zooadd.c 2.34 88/08/15 10:53:11 */
- Xstatic char sccsid[]="@(#) zooadd.c 2.34 88/08/15 10:53:11";
- X#endif /* LINT */
- X
- X/*
- XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
- X(C) Copyright 1988 Rahul Dhesi -- All rights reserved
- X*/
- X#include "options.h"
- X/* Adds files specified in parameter-list to archive zoo_path. */
- X
- X#define LONGEST 20 /* assumed length of longest filename */
- X#include "zoomem.h" /* to define MAXADD */
- X#include "zoo.h"
- X#include "zooio.h"
- X#include "various.h"
- X#include "parse.h"
- X#include "debug.h"
- X
- X#include "portable.h"
- X
- X#include "zoofns.h"
- X#include "errors.i"
- Xextern int break_hit;
- Xextern int quiet;
- X
- X#ifdef LINT_ARGS
- Xvoid show_comment (struct direntry *, ZOOFILE, int, char *);
- Xvoid dosname (char *, char *);
- Xvoid modpath (char *);
- Xvoid opts_add (char *, int *, int *, int *, int *, int *, int *,
- X int *, int *, int *, int *, int *, int *);
- Xint ver_too_high (struct zoo_header *);
- Xget_comment (struct direntry *, ZOOFILE, char *);
- Xvoid copyfields (struct direntry *, struct tiny_header *);
- Xvoid storefname (struct direntry *, char *, int);
- Xchar *choosefname (struct direntry *);
- X#else
- Xvoid show_comment ();
- Xvoid dosname ();
- Xvoid modpath ();
- Xvoid opts_add ();
- Xint ver_too_high ();
- Xget_comment ();
- Xvoid copyfields ();
- Xvoid storefname ();
- Xchar *choosefname ();
- X#endif
- X
- Xextern struct zoo_header zoo_header;
- X
- Xextern char file_leader[];
- Xextern unsigned int crccode;
- X
- Xvoid zooadd(zoo_path, argc, argv, option)
- Xchar *zoo_path; /* pathname of zoo archive to add to */
- Xint argc; /* how many filespecs supplied */
- Xchar **argv; /* array of pointers to filespecs */
- Xchar *option; /* option string */
- X{
- Xchar *whichname; /* which name to show user */
- Xchar *flist[MAXADD]; /* list of ptrs to input fnames */
- Xint fptr; /* will point to within flist */
- XZOOFILE this_file; /* file to add */
- Xchar zoo_fname[LFNAMESIZE]; /* basename of archive itself */
- Xchar zoo_bak[LFNAMESIZE]; /* name of archive's backup */
- Xchar this_fname[LFNAMESIZE]; /* just filename of file to add */
- Xchar latest_name[LFNAMESIZE]; /* latest name in archive */
- Xlong last_old = 0L; /* last direntry in old chain */
- XZOOFILE zoo_file; /* stream for open archive */
- Xchar *this_path; /* pathname of file to add */
- X
- X#ifdef NOENUM
- X#define NEW_ZOO 1
- X#define OLD_ZOO 2
- Xint zoo_status;
- X#else
- Xenum {NEW_ZOO, OLD_ZOO} zoo_status; /* newly created or not */
- X#endif
- X
- Xlong this_dir_offset; /* pointers to within archive */
- Xlong save_position; /* pointer to within archive */
- Xlong prev_pos; /* posn of prev file of same name */
- Xstruct direntry direntry; /* directory entry */
- Xstruct direntry dir2entry; /* spare */
- Xint status; /* error status */
- Xint success; /* successful addition of file? */
- Xint addcount = 0; /* number added */
- Xint update=0; /* only files already in archive */
- Xint suppress=0; /* suppress compression */
- Xint new=0; /* add only files not in archive */
- Xint zootime = 0; /* just set archive time */
- Xint add_comment = 0; /* add comment */
- Xint pack = 0; /* pack after adding */
- Xint need_dir = 1; /* store directories too */
- Xint delcount = 0; /* count of deleted entries */
- Xint exit_status = 0; /* exit status to set */
- X
- Xunsigned int latest_date = 0; /* to set time on archive itself */
- Xunsigned int latest_time = 0; /* .. same */
- Xint move = 0; /* delete after adding to archive */
- Xint longest; /* length of longest pathname added */
- Xint firstfile = 1; /* first file being added? */
- Xint z_fmt = 0; /* look for Z format files? */
- Xint inargs = 0; /* read filenames from stdin? */
- X
- X#ifndef PORTABLE
- Xstruct tiny_header tiny_header; /* for Z format archives */
- X#endif
- X
- Xunsigned this_version_no; /* version no. of old file */
- Xunsigned high_vflag; /* version flag of old file */
- Xunsigned high_version_no; /* highest version no of this file */
- Xlong high_pos; /* offset of file w/highest ver no */
- Xunsigned int fgens; /* gens. to preserve -- file */
- Xunsigned int zgens; /* gens. to preserve -- archive */
- Xlong oldcmtpos; /* to save old comment */
- Xunsigned int oldcmtsiz; /* to save old comment */
- Xint genson = 0; /* whether to turn generations on */
- X
- X/* on entry option points to first letter */
- X
- Xopts_add (option, &zootime, &quiet, &suppress, &move, &new, &pack,
- X &update, &add_comment, &z_fmt, &need_dir, &inargs, &genson);
- X
- X/* POSSIBLE RACE CONDITION BETWEEN TESTING EXISTENCE AND CREATING FILE */
- Xif (exists (zoo_path)) {
- X zoo_file = zooopen (zoo_path, Z_RDWR);
- X zoo_status = OLD_ZOO;
- X} else {
- X if (!zootime)
- X zoo_file = zoocreate (zoo_path);
- X else
- X zoo_file = NOFILE; /* don't create if just setting time */
- X zoo_status = NEW_ZOO;
- X}
- X
- Xif (zoo_file == NOFILE)
- X prterror ('f', could_not_open, zoo_path);
- X
- Xbasename(zoo_path, zoo_fname); /* get basename of archive */
- Xrootname (zoo_path, zoo_bak); /* name without extension */
- Xstrcat (zoo_bak, BACKUP_EXT); /* name of backup of this archive */
- X
- X/* Now we prepare the archive for adding one or more files. If the archive
- Xhas just been created, we write the archive header */
- X
- Xaddfname ("",0L,0,0,0,0); /* initialize table of files already in archive */
- Xif (zoo_status == NEW_ZOO) { /* newly-created archive */
- X if (genson) /* if no generations needed */
- X zoo_header.vdata = (VFL_ON|GEN_DEFAULT); /* generations on */
- X fwr_zooh (&zoo_header, zoo_file);
- X zgens = GEN_DEFAULT;
- X zooseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data begins */
- X} else {
- X /* read header and rewrite with updated version numbers, preserving
- X header type */
- X rwheader (&zoo_header, zoo_file, 1);
- X zgens = zoo_header.vdata & VFL_GEN; /* get archive generations */
- X /* initialize latest_name to null string */
- X /* NOTE: latest_name is not currently used for anything, but
- X may be used in the future for inserting files into the
- X archive in alphabetic order. */
- X *latest_name = '\0';
- X
- X /* Skip existing files but add them to a list. The variable last_old
- X gets the tail of the old chain of directory entries */
- X skip_files (zoo_file, &latest_date, &latest_time, &delcount,
- X latest_name, &last_old);
- X}
- X/* The file pointer is now positioned correctly to add a file to archive,
- Xunless the null directory entry is too short. This will be fixed below. */
- X
- X/* If we are just setting time, do it and run. */
- Xif (zootime) {
- X#ifdef NIXTIME
- X zooclose (zoo_file);
- X setutime (zoo_path, latest_date, latest_time);
- X#else
- X settime (zoo_file, latest_date, latest_time);
- X zooclose (zoo_file);
- X#endif
- X prterror ('m', "Archive time adjusted.\n");
- X zooexit (0);
- X}
- X
- X/* make list of files, excluding archive and its backup */
- Xlongest = LONGEST;
- Xif (!inargs) {
- X makelist(argc, argv, flist, MAXADD-2, zoo_fname, zoo_bak, ".", &longest);
- X /* ^^ ^^ ^^ exclude */
- X}
- X
- Xfptr = 0; /* ready to get filename (if makelist() was called) or to
- X begin adding filenames (if reading them from stdin) */
- X
- Xwhile (1) {
- X unsigned int this_date, this_time;
- X int INLIST; /* boolean */
- X int RECENT; /* boolean */
- X int danger; /* if update requested and disk copy is out of date */
- X if (inargs) {
- X again: /* loop back if filename was same as archive name or its backup */
- X this_path = getstdin(); /* pathname from stdin, in static area */
- X if (this_path != NULL) {
- X if (samefile (nameptr(zoo_fname),nameptr(this_path)) ||
- X samefile (nameptr(zoo_bak),nameptr(this_path)))
- X goto again; /* don't add archive to itself */
- X modpath (this_path);
- X /* if moving files, add to list for later deletion; if list overflows,
- X terminate addition loop and give warning message */
- X if (move) {
- X if (fptr >= MAXADD-2) {
- X prterror ('w', too_many_files, MAXADD-2);
- X this_path = NULL;
- X } else
- X flist[fptr++] = strdup (this_path);
- X }
- X }
- X } else {
- X this_path = flist[fptr++];
- X }
- X /* exit the addition loop when no more pathnames are left */
- X if (this_path == NULL) {
- X /* in case stdin was being read, make sure flist is NULL-terminated */
- X flist[fptr] = NULL;
- X break;
- X }
- X
- X basename (this_path, this_fname); /* get just filename for later */
- X
- X this_file = zooopen(this_path, Z_READ);
- X if (this_file == NOFILE) {
- X prterror ('e', could_not_open, this_path);
- X exit_status++;
- X continue;
- X }
- X
- X#ifndef PORTABLE
- X /* Test to see if this is a Z format file. We assume the file is Z format
- X if (a) tag is correct and (b) type is 1 and (c) embedded filename
- X is not longer than FNAMESIZE.
- X */
- X if (z_fmt) {
- X zooread (this_file, (char *) &tiny_header, sizeof(tiny_header));
- X if (tiny_header.tinytag == TINYTAG && tiny_header.type == 1 &&
- X strlen (tiny_header.fname) <= FNAMESIZE)
- X /* ok */ ;
- X else {
- X zooclose (this_file);
- X prterror ('e', "File %s does not have Z format.\n", this_fname);
- X exit_status++;
- X continue;
- X }
- X }
- X#endif
- X
- X /* get file time; also fix name */
- X#ifndef PORTABLE
- X if (z_fmt) {
- X direntry.date = tiny_header.date;
- X direntry.time = tiny_header.time;
- X strcpy (direntry.fname, tiny_header.fname);
- X direntry.dirlen = direntry.namlen = 0;
- X } else {
- X#endif
- X
- X /* Get timstamp of file being added */
- X#ifdef GETUTIME
- X getutime (this_path, &direntry.date, &direntry.time);
- X#else
- X gettime (this_file, &direntry.date, &direntry.time);
- X#endif
- X
- X /* save file attributes */
- X#ifdef FATTR
- X /* we expect getfattr() to set all attr. bits; currently
- X only the portable format is recognized */
- X {
- X# ifdef FATTR_FNAME
- X unsigned long getfattr PARMS ((char *);
- X direntry.fattr = getfattr (this_path);
- X# else
- X unsigned long getfattr PARMS ((ZOOFILE));
- X direntry.fattr = getfattr (this_file);
- X# endif /* FATTR_FNAME */
- X }
- X#else
- X direntry.fattr = NO_FATTR; /* none */
- X#endif /* FATTR */
- X
- X#ifdef FOLD
- X strlwr(this_fname);
- X#endif
- X dosname (this_fname, direntry.fname); /* MSDOS filename */
- X
- X /*
- X Store long filename into direntry.lfname iff it is different from MSDOS
- X filename. Also store directory name if need_dir is true. Moved out of
- X zooadd() so zooadd() doesn't get too big for optimization.
- X */
- X storefname (&direntry, this_path, need_dir);
- X
- X#ifndef PORTABLE
- X }
- X#endif
- X
- X#ifdef DEBUG
- Xprintf ("zooadd: direntry.lfname = [%s] direntry.dirname = [%s]\n",
- X direntry.lfname, direntry.dirname);
- X#endif
- X
- X /* if update option, then we add file if it is already in the archive
- X AND the archived file is older */
- X
- X /* The following logic was derived from a Karnaugh map so it may
- X be hard to understand. Essentially, if U=update requested,
- X N=new files requested, I=file is already in archive, and
- X R=file being archived is more recent than file already in
- X archive, then the boolean equation is:
- X
- X add = U' (N' + I') + U (IR + I'N)
- X */
- X
- X /* Get the filename to use for this addition. */
- X whichname = choosefname(&direntry);
- X
- X /* Get position in archive of any old file of same name, ignoring
- X any directory prefix if need_dir is not true. Also get its
- X date, time, version flag, and version number. */
- X prev_pos = inlist (fullpath (&direntry), &this_date, &this_time,
- X &this_version_no, &high_vflag, &high_version_no,
- X &high_pos, !need_dir);
- X
- X/* define DBG_INLIST for debugging by printing values returned by inlist() */
- X#ifdef DBG_INLIST
- X printf ("FROM inlist(): prev_pos=%ld, high_pos=%ld\n", prev_pos, high_pos);
- X printf ("this_version_no=%u, high_vflag=%4x, high_version_no=%u\n",
- X this_version_no, high_vflag, high_version_no);
- X#endif
- X
- X INLIST = prev_pos > 0; /* already in archive if positive value */
- X if (INLIST) {
- X int result;
- X result = cmpnum (direntry.date, direntry.time, this_date, this_time);
- X RECENT = result > 0;
- X danger = result < 0;
- X } else
- X danger = 0; /* And RECENT is undefined and should not be used */
- X
- X if (
- X !update && (!new || !INLIST) ||
- X update && (INLIST && RECENT || !INLIST && new)
- X )
- X ; /* then continue and add file */
- X else {
- X if (update && danger)
- X prterror ('w', "Archived copy of %s is newer.\n", whichname);
- X zooclose (this_file);
- X continue; /* cycle back, skip this file */
- X }
- X
- X#ifdef CHEKDIR
- X /* Don't add if this is a directory */
- X if (isadir (this_file)) {
- X zooclose (this_file);
- X continue;
- X }
- X#else
- X# ifdef CHEKUDIR
- X /* Don't add if this is a directory */
- X if (isuadir (this_path)) {
- X zooclose (this_file);
- X continue;
- X }
- X# endif /* CHEKUDIR */
- X#endif /* CHEKDIR */
- X
- X /* Create directory entry for new file (but don't add just yet) */
- X /* NOTE: we already got file date and time above for update option */
- X /* add tag, type, timezone, struc, system_id, and var_dir_len */
- X newdir (&direntry);
- X
- X if (!genson && zoo_status == NEW_ZOO ||
- X (zoo_header.vdata & VFL_ON) == 0) {
- X direntry.vflag = 0;
- X direntry.version_no = 0;
- X }
- X
- X /*
- X Write a null direntry entry. Thus, if an error occurs or the program
- X is interrupted, the end of the archive will still be meaningful.
- X Special check needed for first one written.
- X */
- X
- X direntry.next = direntry.offset = 0L; /* trailing null entry */
- X this_dir_offset = zootell (zoo_file);
- X if (!firstfile) {
- X writedir (&direntry, zoo_file);
- X } else {
- X /*
- X Before adding the first file to the archive, we must make sure that
- X the previous directory chain (if any) is properly terminated with a
- X null entry of the right size. If this is a new archive, we simply
- X write a new null entry of the right size. If this is an existing
- X archive, we must check the size of the previous trailing null entry.
- X If it is too small, we will back up to the most recent real directory
- X entry and change its .next field to point to end of file.
- X */
- X
- X if (zoo_status == NEW_ZOO) {
- X writedir (&direntry, zoo_file); /* write null dir entry */
- X } else {
- X struct direntry tmpentry;
- X long tmppos;
- X int oldlen, newlen;
- X tmppos = zootell (zoo_file);
- X frd_dir (&tmpentry, zoo_file);
- X#define DIRLEN(x) ((x.type<2) ? SIZ_DIR : (SIZ_DIRL+x.var_dir_len))
- X oldlen = DIRLEN(tmpentry); /* get length of direntry */
- X newlen = DIRLEN(direntry); /* ditto */
- X
- X if (newlen > oldlen) { /* trouble */
- X zooseek (zoo_file, last_old, 0); /* back to previous entry */
- X frd_dir (&tmpentry, zoo_file);
- X zooseek (zoo_file, 0L, 2); /* get EOF position */
- X tmpentry.next = zootell (zoo_file); /* point to EOF */
- X zooseek (zoo_file, last_old, 0); /* back to previous entry */
- X writedir (&tmpentry, zoo_file); /* update it */
- X zooseek (zoo_file, 0L, 2); /* to EOF ... */
- X this_dir_offset = zootell (zoo_file);
- X writedir (&direntry, zoo_file); /* ...write null dir entry */
- X } else
- X zooseek (zoo_file, tmppos, 0); /* long enough -- let it be */
- X } /* if (zoo_status == NEW_ZOO) ... */
- X } /* if (!firstfile) ... */
- X
- X /* Now `this_dir_offset' is where the next directory entry will go */
- X
- X /* first file added goes at EOF to avoid overwriting comments */
- X if (firstfile) {
- X zooseek (zoo_file, 0L, 2); /* EOF */
- X direntry.offset = zootell (zoo_file) + SIZ_FLDR;
- X } else {
- X direntry.offset = this_dir_offset + SIZ_DIRL +
- X direntry.var_dir_len + SIZ_FLDR;
- X }
- X
- X direntry.major_ver = MAJOR_EXT_VER; /* minimum version number needed */
- X direntry.minor_ver = MINOR_EXT_VER; /* .. to extract */
- X direntry.deleted = 0; /* not deleted, naturally */
- X direntry.comment = 0L; /* no comment (yet) */
- X direntry.cmt_size = 0; /* .. so no size either */
- X
- X save_position = direntry.offset; /* save position in case of error */
- X
- X zooseek (zoo_file, direntry.offset - SIZ_FLDR, 0);
- X zoowrite (zoo_file, file_leader, SIZ_FLDR);
- X
- X#ifdef PORTABLE
- X prterror ('m', "%-*s -- ", longest, this_path);
- X#else
- X if (z_fmt)
- X prterror ('m', "%-12s <== %-*s -- ",
- X direntry.fname, longest, this_path);
- X else
- X prterror ('m', "%-*s -- ", longest, this_path);
- X
- X#endif /* PORTABLE */
- X
- X crccode = 0;
- X#ifndef PORTABLE
- X if (z_fmt)
- X {
- X direntry.packing_method = tiny_header.packing_method;
- X zooseek (this_file, (long) (sizeof(tiny_header)+tiny_header.cmt_size), 0);
- X status = getfile (this_file, zoo_file, tiny_header.size_now, 1);
- X } else
- X#endif
- X if (suppress) { /* suppress compression */
- X direntry.packing_method = 0; /* no compression */
- X status = getfile (this_file, zoo_file, -1L, 1);
- X } else {
- X#ifdef UNBUF_IO /* unbuffered I/O */
- X long lseek PARMS ((int, long, int));
- X long tell PARMS ((int));
- X int this_fd, zoo_fd;
- X#endif
- X direntry.packing_method = 1; /* compressed */
- X#ifdef UNBUF_IO
- X this_fd = fileno (this_file); /* get .. */
- X zoo_fd = fileno (zoo_file); /* ... file descriptors */
- X zooseek (zoo_file, zootell (zoo_file), 0); /* synch */
- X zooseek (this_file, zootell (this_file), 0); /* synch */
- X status = lzc(this_fd, zoo_fd); /* add with compression */
- X zooseek (zoo_file, tell (zoo_fd), 0); /* resynch */
- X zooseek (this_file, tell (this_fd), 0); /* resynch */
- X#else
- X status = lzc(this_file, zoo_file); /* add with compression */
- X#endif /* UNBUF_IO */
- X
- X }
- X if (status != 0) { /* if I */
- X ++exit_status; /* remember error */
- X if (status == 1)
- X prterror ('F', no_memory);
- X else if (status == 2)
- X prterror ('F', disk_full);
- X else if (status == 3)
- X prterror ('F', "Read error.\n");
- X else
- X prterror ('F', internal_error);
- X success = 0;
- X } else {
- X direntry.next = zootell (zoo_file);
- X direntry.size_now = direntry.next - direntry.offset;
- X
- X /* find and store original size of file just compressed */
- X/*DEBUG VMS*/ zooseek (this_file, 0L, 2); /* seek to EOF */
- X
- X direntry.org_size = zootell (this_file); /* should be EOF already */
- X
- X /* If the compressed one is bigger, just copy */
- X
- X if (direntry.size_now >= direntry.org_size && /* if II */
- X direntry.packing_method != 0) {
- X zooseek (zoo_file, save_position, 0); /* ..restore file pointer */
- X zootrunc (zoo_file); /* ..truncate file */
- X direntry.packing_method = 0; /* ..and just copy */
- X zooseek (this_file, 0L, 0); /* (but rewind first!) */
- X crccode = 0; /* re-start crc from 0 */
- X status = getfile (this_file, zoo_file, -1L, 1);
- X if (status != 0) { /* if III */
- X success = 0;
- X printf (disk_full);
- X exit_status++;
- X } else {
- X success = 1;
- X direntry.next = zootell (zoo_file);
- X direntry.size_now = direntry.next - direntry.offset;
- X } /* end if III */
- X } else {
- X success = 1;
- X } /* end if II */
- X
- X } /* end if I */
- X
- X if (success) { /* file successfully added */
- X addcount++; /* how many added */
- X direntry.file_crc = crccode;
- X
- X /* remember most recent date and time */
- X if (cmpnum (direntry.date,direntry.time,latest_date,latest_time) > 0) {
- X latest_date = direntry.date;
- X latest_time = direntry.time;
- X }
- X
- X#if 0
- X /* mark any previous version of this file in archive as deleted */
- X dir2entry.comment = 0L; /* for later use assigning to direntry */
- X dir2entry.cmt_size = 0;
- X#endif
- X
- X if (!z_fmt)
- X prterror ('M', " (%2d%%) ", cfactor (direntry.org_size, direntry.size_now));
- X
- X oldcmtsiz = 0; /* assume no old comment */
- X oldcmtpos = 0L;
- X
- X if (prev_pos > 0) { /* in archive */
- X int delold = 0; /* delete old? */
- X /* if versions active both archive-wide and for file */
- X if ((zoo_header.vdata & VFL_ON) && (high_vflag & VFL_ON)) {
- X /* next test is optimization, to avoid redundant I/O */
- X if (high_pos != prev_pos || this_version_no == 1) {
- X /* prev highest is no longer highest so adjust vflag */
- X long save_pos = zootell (zoo_file); /*DEBUG*/
- X zooseek (zoo_file, high_pos, 0);
- X readdir (&dir2entry, zoo_file, 1);
- X oldcmtpos = dir2entry.comment;
- X oldcmtsiz = dir2entry.cmt_size;
- X dir2entry.vflag &= (~VFL_LAST); /* no longer highest */
- X zooseek (zoo_file, high_pos, 0);
- X writedir (&dir2entry, zoo_file);
- X zooseek (zoo_file, save_pos, 0); /*DEBUG*/
- X }
- X
- X direntry.version_no = high_version_no + 1; /* ..one higher */
- X direntry.vflag = high_vflag;
- X /* now see if we need to delete older version */
- X fgens = high_vflag & VFL_GEN;
- X if (fgens == 0)
- X fgens = zgens;
- X if (zgens != 0 && zgens < fgens)
- X fgens = zgens;
- X if (fgens != 0 && direntry.version_no - this_version_no >= fgens) {
- X delold = 1;
- X prterror ('M', "replaced+\n");
- X } else
- X prterror ('M', "added+\n");
- X } else {
- X prterror ('M', "replaced\n");
- X delold = 1;
- X }
- X
- X if (delold) { /* deleting old file */
- X long save_pos = zootell (zoo_file); /*DEBUG*/
- X ++delcount; /* remember to pack */
- X zooseek (zoo_file, prev_pos, 0);
- X readdir (&dir2entry, zoo_file, 1);
- X if (dir2entry.cmt_size != 0) { /* propagate latest comment */
- X oldcmtpos = dir2entry.comment;
- X oldcmtsiz = dir2entry.cmt_size;
- X }
- X dir2entry.deleted = 1; /* mark as deleted */
- X /* following line is optimization if only 1 generation */
- X dir2entry.vflag &= (~VFL_LAST); /* no longer highest */
- X zooseek (zoo_file, prev_pos, 0);
- X writedir (&dir2entry, zoo_file);
- X zooseek (zoo_file, save_pos, 0); /*DEBUG*/
- X }
- X } else /* not in archive */
- X prterror ('M', "added\n");
- X
- X /* Preserve any old comment if we replaced or superseded the file */
- X direntry.comment = oldcmtpos;
- X direntry.cmt_size = oldcmtsiz;
- X
- X#ifndef PORTABLE
- X /* Copy comment if any from Z format file */
- X if (z_fmt && tiny_header.cmt_size != 0) {
- X zooseek (this_file, (long) sizeof(tiny_header), 0); /* to comment */
- X direntry.comment = zootell (zoo_file);
- X direntry.cmt_size = tiny_header.cmt_size;
- X /* 4th param is 0 for no CRC */
- X getfile (this_file, zoo_file, (long) tiny_header.cmt_size, 0);
- X direntry.next = zootell (zoo_file);
- X }
- X#endif
- X
- X /* if user requested comments, any previous comment in a Z format
- X file may now be manually overwritten */
- X if (add_comment && !feof (stdin)) {
- X show_comment (&direntry, zoo_file, 1, whichname);
- X get_comment (&direntry, zoo_file, this_path);
- X direntry.next = zootell (zoo_file); /* update .next ptr */
- X } /* end if */
- X
- X#ifndef PORTABLE
- X /* if adding Z format archive, copy relevant fields from its header */
- X if (z_fmt) { /* moved out to shorten code & allow optimizer to work */
- X copyfields (&direntry, &tiny_header);
- X }
- X#endif
- X
- X debug((printf ("zooadd: our new .next = [%lx].\n", direntry.next)))
- X
- X {
- X long savepos = zootell (zoo_file); /* save position */
- X zooseek (zoo_file, this_dir_offset, 0);
- X writedir (&direntry, zoo_file);
- X zooseek (zoo_file, savepos, 0); /* restore position */
- X }
- X
- X } else { /* file was not properly added */
- X zooseek (zoo_file, save_position, 0); /* ..restore file pointer */
- X zootrunc (zoo_file); /* ..truncate file */
- X } /* end if */
- X zooclose (this_file);
- Xif (!success)
- X break;
- Xfirstfile = 0;
- X} /* end for */
- X
- Xsave_position = zootell (zoo_file);
- X
- X/* Write a null direntry entry */
- Xzooseek (zoo_file, save_position, 0);
- Xwritenull (zoo_file, MAXDIRSIZE);
- Xzootrunc (zoo_file); /* truncate */
- X
- X#ifdef NIXTIME
- Xzooclose (zoo_file);
- Xsetutime (zoo_path, latest_date, latest_time);
- X#else
- Xsettime (zoo_file, latest_date, latest_time);
- Xzooclose (zoo_file);
- X#endif
- X
- Xif (!addcount) { /* no files added */
- X prterror ('m', "No files added.\n");
- X if (zoo_status == NEW_ZOO)
- X unlink (zoo_path);
- X} else {
- X if (delcount && pack) { /* pack if user asked and found deleted entries */
- X prterror ('M', "-----\nPacking...");
- X zoopack (zoo_path, "PP");
- X prterror ('M', "done\n");
- X }
- X
- X /* If files to move & we added some and no error so far, delete originals */
- X if (move && !exit_status)
- X if (kill_files (flist, longest) != 0)
- X exit_status++;
- X}
- X
- Xif (exit_status)
- X zooexit (1);
- X} /* end zoo_add */
- END_OF_FILE
- if test 25720 -ne `wc -c <'zooadd.c'`; then
- echo shar: \"'zooadd.c'\" unpacked with wrong size!
- fi
- # end of 'zooadd.c'
- fi
- if test -f 'zoodel.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'zoodel.c'\"
- else
- echo shar: Extracting \"'zoodel.c'\" \(9557 characters\)
- sed "s/^X//" >'zoodel.c' <<'END_OF_FILE'
- X#ifndef LINT
- X/* @(#) zoodel.c 2.19 88/02/06 21:23:36 */
- Xstatic char sccsid[]="@(#) zoodel.c 2.19 88/02/06 21:23:36";
- X#endif /* LINT */
- X
- X/*
- XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
- X(C) Copyright 1988 Rahul Dhesi -- All rights reserved
- X*/
- X#include "options.h"
- X/* Deletes or undeletes entries from an archive. choice=1 requests
- X deletion and choice=0 requests undeletion. */
- X#include "portable.h"
- X#ifndef OK_STDIO
- X#include <stdio.h>
- X#define OK_STDIO
- X#endif
- X#include "various.h" /* may not be needed */
- X#include "zooio.h"
- X#include "zoo.h"
- X#include "zoofns.h"
- X#include "errors.i"
- X
- X#ifndef NOSIGNAL
- X#include <signal.h>
- X#endif
- X
- X#ifdef LINT_ARGS
- Xint needed (char *, struct direntry *, struct zoo_header *);
- Xint ver_too_high (struct zoo_header *);
- X#else
- Xint needed ();
- Xint ver_too_high ();
- X#endif
- X
- Xextern int quiet;
- X
- Xvoid zoodel (zoo_path, option, choice)
- Xchar *zoo_path;
- Xchar *option;
- Xint choice;
- X{
- X#ifndef NOSIGNAL
- X int (*oldsignal)(); /* to save previous SIGINT handler */
- X#endif
- X int delcount = 0; /* how many entries we [un]deleted */
- X char matchname[PATHSIZE]; /* will hold full pathname */
- X register ZOOFILE zoo_file;
- X struct zoo_header zoo_header;
- X struct direntry direntry;
- X unsigned int latest_date = 0; /* so we can set time of archive later */
- X unsigned int latest_time = 0;
- X int pack = 0; /* pack after deletion? */
- X int file_deleted = 0; /* any files deleted? */
- X int one = 0; /* del/undel one file only */
- X int done; /* loop control */
- X int action; /* delete/undelete or adjust generation */
- X int subopt; /* sub option to action */
- X long gencount; /* generation count */
- X int doarchive = 0; /* whether to adjust archive gen count */
- X unsigned valtoshow; /* value to show in informative message */
- X int dodel = 0; /* selection of deleted files */
- X int selected; /* if current direntry selected */
- X
- X/* values for action */
- X#define NO_ACTION 0 /* nothing */
- X#define DEL_UNDEL 1 /* delete or undelete file */
- X#define ADJ_LIM 2 /* adjust generation limit */
- X#define ADJ_GCNT 3 /* adjust generation count */
- X#define GEN_ON 4 /* turn on generations */
- X#define GEN_OFF 5 /* turn off generations */
- X
- X/* values for subopt */
- X#define SET 0
- X#define INC 1
- X
- Xaction = NO_ACTION;
- Xif (*option == 'g') {
- X while (*(++option)) {
- X switch (*option) {
- X case 'A': doarchive = 1; break;
- X case 'q': quiet++; break;
- X case 'l': action = ADJ_LIM; break;
- X case 'c': action = ADJ_GCNT; break;
- X case '=':
- X subopt = SET; gencount = calc_ofs (++option);
- X if (action == ADJ_GCNT && gencount == 0)
- X prterror ('f', "Generation count must be nonzero.\n");
- X goto opts_done;
- X case '+':
- X if (action == NO_ACTION) {
- X if (option[1] =='\0') {
- X action = GEN_ON;
- X goto opts_done;
- X } else
- X prterror ('f', garbled);
- X } else {
- X subopt = INC; gencount = calc_ofs (++option);
- X goto opts_done;
- X }
- X case '-':
- X if (action == NO_ACTION) {
- X if (option[1] =='\0') {
- X action = GEN_OFF;
- X goto opts_done;
- X } else
- X prterror ('f', garbled);
- X } else {
- X subopt = INC; gencount = - calc_ofs (++option);
- X goto opts_done;
- X }
- X case 'd':
- X dodel++; break;
- X default:
- X prterror ('f', garbled);
- X } /* end switch */
- X } /* end while */
- X /* if normal exit from while loop, it means bad command string */
- X prterror ('f', garbled);
- X opts_done: /* jump here from exit in while loop above */
- X if (action == NO_ACTION)
- X prterror ('f', garbled);
- X} else {
- X action = DEL_UNDEL;
- X while (*(++option)) {
- X switch (*option) {
- X case 'P': pack++; break; /* pack after adding */
- X case 'q': quiet++; break; /* be quiet */
- X case '1': one++; break; /* del or undel only one file */
- X default:
- X prterror ('f', inv_option, *option);
- X }
- X } /* end while */
- X}
- X
- X /* Open archive for read/write/binary access. It must already exist */
- X if ((zoo_file = zooopen (zoo_path, Z_RDWR)) == NOFILE) {
- X prterror ('f', could_not_open, zoo_path);
- X }
- X
- X /* read archive header */
- X frd_zooh (&zoo_header, zoo_file);
- X if ((zoo_header.zoo_start + zoo_header.zoo_minus) != 0L)
- X prterror ('f', failed_consistency);
- X if (ver_too_high (&zoo_header))
- X prterror ('f', wrong_version, zoo_header.major_ver, zoo_header.minor_ver);
- X
- X if (doarchive) { /* manipulate archive gen val */
- X unsigned zoo_date, zoo_time;
- X#ifdef GETUTIME
- X getutime (zoo_path, &zoo_date, &zoo_time); /* save archive timestamp */
- X#else
- X gettime (zoo_file, &zoo_date, &zoo_time);
- X#endif
- X if (zoo_header.type == 0)
- X prterror ('f', packfirst);
- X if (action == ADJ_LIM) {
- X unsigned newgencount;
- X if (subopt == SET)
- X newgencount = (unsigned) gencount;
- X else /* INC */
- X newgencount = (zoo_header.vdata & VFL_GEN) + (unsigned) gencount;
- X newgencount &= VFL_GEN; /* reduce to allowed bits */
- X zoo_header.vdata &= (~VFL_GEN);
- X zoo_header.vdata |= newgencount;
- X prterror ('M', "Archive generation limit is now %u\n", newgencount);
- X } else if (action == GEN_ON) {
- X zoo_header.vdata |= VFL_ON;
- X prterror ('M', "Archive generations on\n");
- X } else if (action == GEN_OFF) {
- X zoo_header.vdata &= (~VFL_ON);
- X prterror ('M', "Archive generations off\n");
- X } else
- X prterror ('f', garbled);
- X zooseek (zoo_file, 0L, 0); /* back to begining of file */
- X fwr_zooh (&zoo_header, zoo_file);
- X#ifdef NIXTIME
- X zooclose (zoo_file);
- X setutime (zoo_path, zoo_date, zoo_time); /* restore archive timestamp */
- X#else
- X settime (zoo_file, zoo_date, zoo_time);
- X zooclose (zoo_file);
- X#endif
- X return;
- X }
- X
- X zooseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data begins */
- X
- X done = 0; /* loop not done yet */
- X while (1) {
- X long this_dir_offset;
- X this_dir_offset = zootell (zoo_file); /* save pos'n of this dir entry */
- X frd_dir (&direntry, zoo_file);
- X if (direntry.zoo_tag != ZOO_TAG) {
- X prterror ('f', bad_directory);
- X }
- X if (direntry.next == 0L) { /* END OF CHAIN */
- X break; /* EXIT on end of chain */
- X }
- X
- X /* select directory entry if it matches criteria */
- X selected = (
- X (action == DEL_UNDEL && direntry.deleted != choice)
- X ||
- X (action != DEL_UNDEL &&
- X (dodel && direntry.deleted ||
- X (dodel < 2 && !direntry.deleted))
- X )
- X );
- X
- X /* WARNING: convention of choice=1 for deleted entry must be same as
- X in direntry definition in zoo.h */
- X
- X /* Test for "done" so if "one" option requested, [un]del only 1 file */
- X /* But we go through the whole archive to adjust archive time */
- X
- X strcpy (matchname, fullpath (&direntry)); /* get full pathname */
- X if (zoo_header.vdata & VFL_ON)
- X add_version (matchname, &direntry); /* add version suffix */
- X
- X if (!done && selected && needed(matchname, &direntry, &zoo_header)) {
- X prterror ('m', "%-14s -- ", matchname);
- X delcount++;
- X if (action == DEL_UNDEL) {
- X direntry.deleted = choice;
- X if (choice)
- X file_deleted++; /* remember if any files actually deleted */
- X } else { /* ADJ_LIM or ADJ_GENCNT */
- X if (direntry.vflag & VFL_ON) { /* skip if no versions */
- X if (action == ADJ_LIM) {
- X unsigned newgencount;
- X if (subopt == SET)
- X newgencount = (unsigned) gencount;
- X else /* INC */
- X newgencount =
- X (int) (direntry.vflag & VFL_GEN) + (int) gencount;
- X newgencount &= VFL_GEN;
- X direntry.vflag &= (~VFL_GEN);
- X direntry.vflag |= newgencount;
- X valtoshow = newgencount;
- X } else { /* ADJ_GCNT */
- X if (subopt == SET)
- X direntry.version_no = (unsigned) gencount;
- X else /* INC */
- X direntry.version_no += (int) gencount;
- X direntry.version_no &= VER_MASK; /* avoid extra bits */
- X valtoshow = direntry.version_no;
- X }
- X }
- X }
- X
- X zooseek (zoo_file, this_dir_offset, 0);
- X
- X#ifndef NOSIGNAL
- X oldsignal = signal (SIGINT, SIG_IGN); /* disable ^C for write */
- X#endif
- X if (fwr_dir (&direntry, zoo_file) == -1)
- X prterror ('f', "Could not write to archive\n");
- X#ifndef NOSIGNAL
- X signal (SIGINT, oldsignal);
- X#endif
- X if (action == DEL_UNDEL)
- X prterror ('M', choice ? "deleted\n" : "undeleted\n");
- X else {
- X if (direntry.vflag & VFL_ON)
- X prterror ('M', "adjusted to %u\n", valtoshow);
- X else
- X prterror ('M', "no generations\n");
- X }
- X if (one)
- X done = 1; /* if 1 option, done after 1 file */
- X }
- X
- X /* remember most recent date and time if entry is not deleted */
- X if (!direntry.deleted)
- X if (direntry.date > latest_date ||
- X (direntry.date == latest_date && direntry.time > latest_time)) {
- X latest_date = direntry.date;
- X latest_time = direntry.time;
- X }
- X zooseek (zoo_file, direntry.next, 0); /* ..seek to next dir entry */
- X } /* endwhile */
- X
- X if (!delcount)
- X printf ("Zoo: No files matched.\n");
- X else {
- X#ifdef NIXTIME
- X zooclose (zoo_file);
- X setutime (zoo_path, latest_date, latest_time);
- X#else
- X#if 0
- X fflush (zoo_file); /* superstition: might help time stamp */
- X#endif
- X settime (zoo_file, latest_date, latest_time);
- X#endif
- X }
- X
- X#ifndef NIXTIME
- Xzooclose (zoo_file);
- X#endif
- X
- Xif (file_deleted && pack) { /* pack if files were deleted and user asked */
- X prterror ('M', "-----\nPacking...");
- X zoopack (zoo_path, "PP");
- X prterror ('M', "done\n");
- X}
- X
- X}
- END_OF_FILE
- if test 9557 -ne `wc -c <'zoodel.c'`; then
- echo shar: \"'zoodel.c'\" unpacked with wrong size!
- fi
- # end of 'zoodel.c'
- fi
- echo shar: End of archive 9 \(of 10\).
- cp /dev/null ark9isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 10 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-